<template>
  <view class="form">
    <view 
      v-for="(field, index) in fields" 
      :key="field.name"
      class="form__field"
      :class="{
        'form__field--error': hasError(field.name),
        'form__field--required': field.required,
        'form__field--disabled': field.disabled
      }"
    >
      <!-- 字段标签 -->
      <view v-if="field.label" class="form__label">
        <text class="form__label-text">{{ field.label }}</text>
        <text v-if="field.required" class="form__label-required">*</text>
      </view>
      
      <!-- 输入框 -->
      <template v-if="field.type === 'input'">
        <Input
          v-model="formData[field.name]"
          :type="field.inputType || 'text'"
          :placeholder="field.placeholder"
          :disabled="field.disabled"
          :readonly="field.readonly"
          :maxlength="field.maxlength"
          :clearable="field.clearable"
          :show-password="field.showPassword"
          :prefix-icon="field.prefixIcon"
          :suffix-icon="field.suffixIcon"
          @input="handleInput(field.name, $event)"
          @blur="handleBlur(field.name)"
          @focus="handleFocus(field.name)"
        />
      </template>
      
      <!-- 文本域 -->
      <template v-else-if="field.type === 'textarea'">
        <Input
          v-model="formData[field.name]"
          type="textarea"
          :placeholder="field.placeholder"
          :disabled="field.disabled"
          :readonly="field.readonly"
          :maxlength="field.maxlength"
          :rows="field.rows || 4"
          :show-count="field.showCount"
          @input="handleInput(field.name, $event)"
          @blur="handleBlur(field.name)"
          @focus="handleFocus(field.name)"
        />
      </template>
      
      <!-- 选择器 -->
      <template v-else-if="field.type === 'select'">
        <u-picker
          v-model="formData[field.name]"
          :columns="field.options"
          :placeholder="field.placeholder"
          :disabled="field.disabled"
          @change="handleInput(field.name, $event)"
        ></u-picker>
      </template>
      
      <!-- 日期选择器 -->
      <template v-else-if="field.type === 'date'">
        <u-datetime-picker
          v-model="formData[field.name]"
          :mode="field.dateMode || 'date'"
          :placeholder="field.placeholder"
          :disabled="field.disabled"
          :min-date="field.minDate"
          :max-date="field.maxDate"
          @change="handleInput(field.name, $event)"
        ></u-datetime-picker>
      </template>
      
      <!-- 开关 -->
      <template v-else-if="field.type === 'switch'">
        <view class="form__switch-wrapper">
          <u-switch
            v-model="formData[field.name]"
            :disabled="field.disabled"
            :size="field.size || 'default'"
            @change="handleInput(field.name, $event)"
          ></u-switch>
          <text v-if="field.switchText" class="form__switch-text">
            {{ field.switchText }}
          </text>
        </view>
      </template>
      
      <!-- 单选框组 -->
      <template v-else-if="field.type === 'radio'">
        <u-radio-group
          v-model="formData[field.name]"
          :disabled="field.disabled"
          @change="handleInput(field.name, $event)"
        >
          <u-radio
            v-for="option in field.options"
            :key="option.value"
            :name="option.value"
            :disabled="option.disabled"
          >
            {{ option.label }}
          </u-radio>
        </u-radio-group>
      </template>
      
      <!-- 复选框组 -->
      <template v-else-if="field.type === 'checkbox'">
        <u-checkbox-group
          v-model="formData[field.name]"
          :disabled="field.disabled"
          @change="handleInput(field.name, $event)"
        >
          <u-checkbox
            v-for="option in field.options"
            :key="option.value"
            :name="option.value"
            :disabled="option.disabled"
          >
            {{ option.label }}
          </u-checkbox>
        </u-checkbox-group>
      </template>
      
      <!-- 文件上传 -->
      <template v-else-if="field.type === 'upload'">
        <u-upload
          v-model="formData[field.name]"
          :action="field.action"
          :max-count="field.maxCount || 1"
          :max-size="field.maxSize"
          :accept="field.accept"
          :disabled="field.disabled"
          @change="handleInput(field.name, $event)"
        ></u-upload>
      </template>
      
      <!-- 自定义插槽 -->
      <template v-else-if="field.type === 'slot'">
        <slot :name="field.name" :field="field" :value="formData[field.name]"></slot>
      </template>
      
      <!-- 错误提示 -->
      <view v-if="hasError(field.name)" class="form__error">
        <u-icon name="error-circle-fill" size="28rpx" color="#ff4757"></u-icon>
        <text class="form__error-text">{{ getError(field.name) }}</text>
      </view>
      
      <!-- 帮助文本 -->
      <view v-if="field.help && !hasError(field.name)" class="form__help">
        <text class="form__help-text">{{ field.help }}</text>
      </view>
    </view>
    
    <!-- 表单操作按钮 -->
    <view v-if="showActions" class="form__actions">
      <Button
        v-if="showCancel"
        type="outline"
        size="lg"
        :disabled="loading"
        @click="handleCancel"
      >
        {{ cancelText || $t('common.cancel') }}
      </Button>
      <Button
        type="primary"
        size="lg"
        :loading="loading"
        :disabled="!isValid"
        @click="handleSubmit"
      >
        {{ submitText || $t('common.submit') }}
      </Button>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick } from 'vue'
import Input from './Input.vue'
import Button from './Button.vue'

interface FormOption {
  label: string
  value: any
  disabled?: boolean
}

interface FormField {
  name: string
  label?: string
  type: 'input' | 'textarea' | 'select' | 'date' | 'switch' | 'radio' | 'checkbox' | 'upload' | 'slot'
  inputType?: 'text' | 'password' | 'number' | 'email' | 'tel'
  placeholder?: string
  required?: boolean
  disabled?: boolean
  readonly?: boolean
  maxlength?: number
  clearable?: boolean
  showPassword?: boolean
  prefixIcon?: string
  suffixIcon?: string
  rows?: number
  showCount?: boolean
  options?: FormOption[]
  dateMode?: 'date' | 'time' | 'datetime'
  minDate?: string
  maxDate?: string
  size?: 'small' | 'default' | 'large'
  switchText?: string
  action?: string
  maxCount?: number
  maxSize?: number
  accept?: string
  help?: string
  rules?: FormRule[]
}

interface FormRule {
  required?: boolean
  min?: number
  max?: number
  pattern?: RegExp
  validator?: (value: any) => boolean | string
  message?: string
}

interface Props {
  // 表单字段配置
  fields: FormField[]
  // 表单数据
  modelValue: Record<string, any>
  // 是否显示操作按钮
  showActions?: boolean
  // 是否显示取消按钮
  showCancel?: boolean
  // 提交按钮文本
  submitText?: string
  // 取消按钮文本
  cancelText?: string
  // 是否加载中
  loading?: boolean
  // 是否立即验证
  validateOnChange?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  showActions: true,
  showCancel: true,
  validateOnChange: true
})

interface Emits {
  'update:modelValue': [value: Record<string, any>]
  submit: [data: Record<string, any>]
  cancel: []
  change: [name: string, value: any]
  focus: [name: string]
  blur: [name: string]
}

const emit = defineEmits<Emits>()

// 响应式数据
const formData = ref<Record<string, any>>({ ...props.modelValue })
const errors = ref<Record<string, string>>({})
const touched = ref<Record<string, boolean>>({})

// 计算属性
const isValid = computed(() => {
  return Object.keys(errors.value).length === 0 && 
         props.fields.filter(field => field.required).every(field => {
           const value = formData.value[field.name]
           return value !== undefined && value !== null && value !== '' && 
                  (Array.isArray(value) ? value.length > 0 : true)
         })
})

// 监听外部数据变化
watch(() => props.modelValue, (newValue) => {
  formData.value = { ...newValue }
}, { deep: true })

// 监听内部数据变化
watch(formData, (newValue) => {
  emit('update:modelValue', { ...newValue })
}, { deep: true })

// 验证单个字段
const validateField = (name: string): boolean => {
  const field = props.fields.find(f => f.name === name)
  if (!field || !field.rules) {
    delete errors.value[name]
    return true
  }
  
  const value = formData.value[name]
  
  for (const rule of field.rules) {
    // 必填验证
    if (rule.required && (value === undefined || value === null || value === '' || 
        (Array.isArray(value) && value.length === 0))) {
      errors.value[name] = rule.message || `${field.label || field.name}是必填项`
      return false
    }
    
    // 如果值为空且不是必填，跳过其他验证
    if (!value && !rule.required) continue
    
    // 最小长度验证
    if (rule.min !== undefined && value.length < rule.min) {
      errors.value[name] = rule.message || `${field.label || field.name}最少${rule.min}个字符`
      return false
    }
    
    // 最大长度验证
    if (rule.max !== undefined && value.length > rule.max) {
      errors.value[name] = rule.message || `${field.label || field.name}最多${rule.max}个字符`
      return false
    }
    
    // 正则验证
    if (rule.pattern && !rule.pattern.test(value)) {
      errors.value[name] = rule.message || `${field.label || field.name}格式不正确`
      return false
    }
    
    // 自定义验证
    if (rule.validator) {
      const result = rule.validator(value)
      if (result !== true) {
        errors.value[name] = typeof result === 'string' ? result : 
                            (rule.message || `${field.label || field.name}验证失败`)
        return false
      }
    }
  }
  
  delete errors.value[name]
  return true
}

// 验证所有字段
const validateAll = (): boolean => {
  let isValid = true
  
  for (const field of props.fields) {
    if (!validateField(field.name)) {
      isValid = false
    }
  }
  
  return isValid
}

// 判断字段是否有错误
const hasError = (name: string): boolean => {
  return !!errors.value[name]
}

// 获取字段错误信息
const getError = (name: string): string => {
  return errors.value[name] || ''
}

// 事件处理
const handleInput = (name: string, value: any) => {
  formData.value[name] = value
  emit('change', name, value)
  
  if (props.validateOnChange && touched.value[name]) {
    nextTick(() => {
      validateField(name)
    })
  }
}

const handleFocus = (name: string) => {
  emit('focus', name)
}

const handleBlur = (name: string) => {
  touched.value[name] = true
  emit('blur', name)
  
  if (props.validateOnChange) {
    validateField(name)
  }
}

const handleSubmit = () => {
  // 标记所有字段为已触摸
  props.fields.forEach(field => {
    touched.value[field.name] = true
  })
  
  if (validateAll()) {
    emit('submit', { ...formData.value })
  }
}

const handleCancel = () => {
  emit('cancel')
}

// 暴露方法
defineExpose({
  validate: validateAll,
  validateField,
  clearErrors: () => {
    errors.value = {}
  },
  resetForm: () => {
    formData.value = {}
    errors.value = {}
    touched.value = {}
  }
})
</script>

<style lang="scss" scoped>
.form {
  padding: 32rpx;
}

.form__field {
  margin-bottom: 32rpx;
  
  &:last-child {
    margin-bottom: 0;
  }
  
  &--error {
    .form__label-text {
      color: #ff4757;
    }
  }
  
  &--disabled {
    opacity: 0.6;
  }
}

.form__label {
  display: flex;
  align-items: center;
  margin-bottom: 16rpx;
}

.form__label-text {
  font-size: 28rpx;
  color: var(--text-color, #333333);
  font-weight: 500;
  transition: color 0.2s ease;
}

.form__label-required {
  color: #ff4757;
  font-size: 28rpx;
  margin-left: 8rpx;
}

.form__switch-wrapper {
  display: flex;
  align-items: center;
  gap: 16rpx;
}

.form__switch-text {
  font-size: 28rpx;
  color: var(--text-color, #333333);
}

.form__error {
  display: flex;
  align-items: center;
  gap: 8rpx;
  margin-top: 12rpx;
  padding: 8rpx 16rpx;
  background: rgba(255, 71, 87, 0.1);
  border-radius: 8rpx;
}

.form__error-text {
  font-size: 24rpx;
  color: #ff4757;
  flex: 1;
}

.form__help {
  margin-top: 12rpx;
  padding: 8rpx 16rpx;
  background: var(--bg-color-light, #f8f9fa);
  border-radius: 8rpx;
}

.form__help-text {
  font-size: 24rpx;
  color: var(--text-color-secondary, #666666);
  line-height: 1.4;
}

.form__actions {
  display: flex;
  gap: 24rpx;
  margin-top: 48rpx;
  padding-top: 32rpx;
  border-top: 2rpx solid var(--border-color-light, #f0f0f0);
  
  :deep(.button) {
    flex: 1;
  }
}

// 响应式设计
@media (max-width: 750rpx) {
  .form {
    padding: 24rpx;
  }
  
  .form__field {
    margin-bottom: 24rpx;
  }
  
  .form__label-text {
    font-size: 26rpx;
  }
  
  .form__actions {
    margin-top: 32rpx;
    padding-top: 24rpx;
    gap: 16rpx;
  }
}

// 暗色主题适配
[data-theme='dark'] {
  .form {
    --text-color: #ffffff;
    --text-color-secondary: #8e8e93;
    --bg-color-light: #2c2c2e;
    --border-color-light: #38383a;
  }
}
</style>